package com.jy.appmarket.newnetwork.api;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import org.json.JSONObject;

import com.jy.appmarket.newnetwork.AuthFailureError;
import com.jy.appmarket.newnetwork.NetworkResponse;
import com.jy.appmarket.newnetwork.ParseError;
import com.jy.appmarket.newnetwork.Request;
import com.jy.appmarket.newnetwork.Response;
import com.jy.appmarket.newnetwork.Response.ErrorListener;
import com.jy.appmarket.newnetwork.Response.Listener;
import com.jy.appmarket.newnetwork.http.HttpHeaderParser;
import com.jy.appmarket.newnetwork.http.HttpUtils;

import android.content.pm.PackageInfo;
import android.os.Build;
import android.text.TextUtils;

public class ApiRequest extends Request<ApiResult> {
	private static String URL_PREFIX;
	private static String SECRET_KEY;
	private static boolean DEBUG = false;// BuildConfig.DEBUG ;

	static {
		if (DEBUG) {
			URL_PREFIX = "http://192.168.1.200:8888/market-service/api/v1/";
			SECRET_KEY = "www.520jy.com";
		} else {
			URL_PREFIX = "http://market.aijiaoyan.com/api/v1/";
			SECRET_KEY = "vx8ea3uz";
		}
	}

	private final Listener<ApiResult> mListener;
	private final byte[] mRequestBody;
	private final String mContentType;

	public static ApiRequest get(String api, Listener<ApiResult> listener, ErrorListener errorListener) {
		return get(api, null, listener, errorListener);

	}

	public static ApiRequest get(String api, Map<String, String> getParams, Listener<ApiResult> listener,
			ErrorListener errorListener) {
		String url = createUrl(api, getParams, null);
		return new ApiRequest(Method.GET, url, null, null, listener, errorListener);
	}

	public static ApiRequest postParam(String api, Map<String, String> getParams, Map<String, String> postParams,
			Listener<ApiResult> listener, ErrorListener errorListener) {
		String url = createUrl(api, getParams, postParams);
		byte[] bytes = encodeParams(postParams);
		String contentType = "application/x-www-form-urlencoded";
		return new ApiRequest(Method.POST, url, contentType, bytes, listener, errorListener);
	}

	public static ApiRequest postJson(String api, Map<String, String> getParams, JSONObject body,
			Listener<ApiResult> listener, ErrorListener errorListener) {
		String url = createUrl(api, getParams, null);
		byte[] bytes = null;
		try {
			bytes = body.toString().getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		String contentType = "application/json; charset=utf-8";
		return new ApiRequest(Method.POST, url, contentType, bytes, listener, errorListener);
	}

	public static void cancel(ApiRequest req) {
		if (req != null) {
			req.cancel();
		}
	}

	private ApiRequest(int method, String url, String contentType, byte[] requestBody, Listener<ApiResult> listener,
			ErrorListener errorListener) {
		super(method, url, errorListener);
		mListener = listener;
		mRequestBody = requestBody;
		mContentType = contentType;
	}

	private static byte[] encodeParams(Map<String, String> params) {
		if (params == null || params.isEmpty()) {
			return null;
		}

		StringBuilder sb = new StringBuilder();
		for (String k : params.keySet()) {
			sb.append(HttpUtils.urlEncode(k));
			sb.append('=');
			sb.append(HttpUtils.urlEncode(params.get(k)));
			sb.append('&');
		}
		sb.deleteCharAt(sb.length() - 1);// remove last &
		String s = sb.toString();
		try {
			return s.getBytes("UTF-8");
		} catch (Exception e) {
		}
		return null;
	}

	private static String createUrl(String api, Map<String, String> getParams, Map<String, String> postParams) {
		TreeMap<String, String> params = new TreeMap<String, String>();
		addCommonParams(params);
		if (getParams != null) {
			params.putAll(getParams);
		}
		if (postParams != null) {
			params.putAll(postParams);
		}

		StringBuilder sb = new StringBuilder(URL_PREFIX).append(api).append('?');
		for (String k : params.keySet()) {
			sb.append(HttpUtils.urlEncode(k));
			sb.append('=');
			sb.append(HttpUtils.urlEncode(params.get(k)));
			sb.append('&');
		}
		String chksum = calculateChecksum(api, params);
		sb.append("_cs").append('=').append(chksum);
		return sb.toString();

	}

	private static String calculateChecksum(String api, final TreeMap<String, String> params) {
		if (params == null) {
			return "";
		}

		StringBuilder sb = new StringBuilder();
		for (String key : params.keySet()) {
			String value = params.get(key);
			if (value != null) {
				sb.append(value);
			}
			sb.append("&");
		}

		sb.append(SECRET_KEY).append('&').append(api);
		return CryptoUtil.md5(sb.toString());
	}

	private static void addCommonParams(Map<String, String> params) {
		String aid = MarketApi.getAndroidId();
		if (!TextUtils.isEmpty(aid)) {
			params.put("_aid", aid);
		}
		String[] info = MarketApi.getTelephoneInfo();
		if (info != null) {
			params.put("_mid", info[0]);
			params.put("_sop", info[1]);
			params.put("_sid", info[2]);
		}

		PackageInfo pi = MarketApi.getMyPackageInfo();
		if (pi != null) {
			params.put("_vn", pi.versionName);
			params.put("_vc", String.valueOf(pi.versionCode));
		}
		params.put("_ch", MarketApi.getMetaString("CHANNEL"));
		params.put("_pn", MarketApi.getMyPackageName());
		params.put("_mnum", MarketApi.getMagic());

		String userId = MarketApi.getUserId();
		if (!TextUtils.isEmpty(userId)) {
			params.put("userId", userId);
		}
	}

	@Override
	public Map<String, String> getHeaders() {

		StringBuilder info = new StringBuilder();
		info.append("_bd=").append(HttpUtils.urlEncode(Build.BRAND));
		info.append("&_md=").append(HttpUtils.urlEncode(Build.MODEL));
		String net = MarketApi.currentNetworkType();

		if (!TextUtils.isEmpty(net)) {
			info.append("&_nw=").append(net);
		}

		String screenSize = MarketApi.getScreenSize();
		if (!TextUtils.isEmpty(screenSize)) {
			info.append("&_wh=").append(screenSize);
		}

		String[] location = MarketApi.getLocation();
		if (location != null) {
			if (!TextUtils.isEmpty(location[0])) {
				info.append("&_lc=").append(HttpUtils.urlEncode(location[0]));
			}

			if (!TextUtils.isEmpty(location[1])) {
				info.append("&_lg=").append(HttpUtils.urlEncode(location[1]));
			}
			if (!TextUtils.isEmpty(location[2])) {
				info.append("&_lt=").append(HttpUtils.urlEncode(location[2]));
			}
		}

		info.append("&_ts=").append(System.currentTimeMillis());
		Map<String, String> baseHeaders = new HashMap<String, String>();
		baseHeaders.put("X-JiaoYan-Device", info.toString());
		return baseHeaders;
	}

	@Override
	protected void deliverResponse(ApiResult response) {
		if (mListener != null) {
			mListener.onResponse(response);
		}
	}

	@Override
	protected Response<ApiResult> parseNetworkResponse(NetworkResponse response) {
		try {
			String charset = HttpHeaderParser.parseCharset(response.headers, "UTF-8");
			ApiResult result = new ApiResult(getSequence(), new String(response.data, charset));
			return Response.success(result, HttpHeaderParser.parseCacheHeaders(response));
		} catch (Exception e) {
			e.printStackTrace();
			return Response.error(new ParseError(e));
		}
	}

	@Override
	public String getBodyContentType() {
		return mContentType;
	}

	@Override
	public byte[] getBody() {
		return mRequestBody;
	}

	public static class ParamBuilder {
		private Map<String, String> map = new HashMap<String, String>();

		public static ParamBuilder create() {
			return new ParamBuilder();
		}

		public ParamBuilder add(String key, String val) {
			map.put(key, val);
			return this;
		}

		public ParamBuilder add(String key, int val) {
			map.put(key, String.valueOf(val));
			return this;
		}

		public Map<String, String> build() {
			return map;
		}
	}
}